package casbinx

import (
	"context"
	"fmt"

	"gitee.com/chunanyong/zorm"
)

// sql语句
var initDBSQLs = map[string][]string{
	"mysql": {
		`show tables like '%s'`,
		`
		create table %s (
			id bigint not null auto_increment,
			ptype varchar(255) default null,
			v0 varchar(255) default null,
			v1 varchar(255) default null,
			v2 varchar(255) default null,
			v3 varchar(255) default null,
			v4 varchar(255) default null,
			v5 varchar(255) default null,
			primary key (id)
		)`,
		`insert into %s (ptype, v0, v1, v2, v3, v4, v5) values ('p', '*', '/v1/demo/*', 'POST', '', '', '')`,
	},
	"postgresql": {
		`select * from pg_class where relname = '%s'`,
		`create table %s (
			id bigserial not null,
			ptype character varying(255),
			v0 character varying(255),
			v1 character varying(255),
			v2 character varying(255),
			v3 character varying(255),
			v4 character varying(255),
			v5 character varying(255),
			primary key (id)
		)`,
		`insert into %s (ptype, v0, v1, v2, v3, v4, v5) values ('p', '*', '/v1/demo/*', 'POST', '', '', '')`,
	},
	"sqlite": {
		`select * from sqlite_master where type = 'table' and name ='%s'`,
		`create table %s (
			id integer primary key autoincrement not null,
			ptype varchar(255),
			v0 varchar(255),
			v1 varchar(255),
			v2 varchar(255),
			v3 varchar(255),
			v4 varchar(255),
			v5 varchar(255)
		)`,
		`insert into %s (ptype, v0, v1, v2, v3, v4, v5) values ('p', '*', '/v1/demo/*', 'POST', '', '', '')`,
	},
}

// InitDB 初始化casbin数据库
func InitDB(cfg Config, dbDao *zorm.DBDao) error {
	ctx := context.Background()
	var err error
	if ctx, err = dbDao.BindContextDBConnection(ctx); err != nil {
		return err
	}
	dbCfg, err := zorm.GetContextDataSourceConfig(ctx)
	if err != nil {
		return err
	}

	finder := zorm.NewFinder()
	finder.Append(fmt.Sprintf(initDBSQLs[dbCfg.Dialect][0], cfg.CasbinRuleTable))
	finder.InjectionCheck = false
	if has, err := zorm.QueryRowMap(ctx, finder); err != nil {
		return err
	} else if len(has) == 0 { // casbin表不存在
		_, err := zorm.Transaction(ctx, func(ctx context.Context) (any, error) {
			for idx, sql := range initDBSQLs[dbCfg.Dialect] {
				if idx == 0 {
					continue
				}
				finder = zorm.NewFinder()
				finder.Append(fmt.Sprintf(sql, cfg.CasbinRuleTable))
				finder.InjectionCheck = false
				if _, err := zorm.UpdateFinder(ctx, finder); err != nil {
					return nil, err
				}
			}

			return nil, nil
		})
		return err
	}
	// 已存在忽略
	return nil
}
